﻿using System;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using CaptureImageTool;
using System.Speech.Synthesis;
using System.Windows.Documents;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
namespace testProject
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        GeometryModel3D mGeometry;
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
            MeshGeometry3D mesh = new MeshGeometry3D();

            //Define 3D mesh object
            //front face
            //mesh.Positions.Add(new Point3D(-0.5, -0.5, 1));
            //mesh.Positions.Add(new Point3D(0.5, -0.5, 1));
            //mesh.Positions.Add(new Point3D(0.5, 0.5, 1));
            //mesh.Positions.Add(new Point3D(-0.5, 0.5, 1));

            mesh.Positions.Add(new Point3D(0, 0, 1));
            mesh.Positions.Add(new Point3D(0, 0, 1));
            mesh.Positions.Add(new Point3D(0, 0, 1));
            mesh.Positions.Add(new Point3D(0, 0, 1));

            //front face
            mesh.Positions.Add(new Point3D(-1, -1, -1));
            mesh.Positions.Add(new Point3D(1, -1, -1));
            mesh.Positions.Add(new Point3D(1, 1, -1));
            mesh.Positions.Add(new Point3D(-1, 1, -1));

            mesh.TriangleIndices.Add(0);
            mesh.TriangleIndices.Add(1);
            mesh.TriangleIndices.Add(2);
            mesh.TriangleIndices.Add(2);
            mesh.TriangleIndices.Add(3);
            mesh.TriangleIndices.Add(0);

            //back face
            mesh.TriangleIndices.Add(6);
            mesh.TriangleIndices.Add(5);
            mesh.TriangleIndices.Add(4);
            mesh.TriangleIndices.Add(4);
            mesh.TriangleIndices.Add(7);
            mesh.TriangleIndices.Add(6);

            //right face
            mesh.TriangleIndices.Add(5);
            mesh.TriangleIndices.Add(6);
            mesh.TriangleIndices.Add(2);
            mesh.TriangleIndices.Add(2);
            mesh.TriangleIndices.Add(1);
            mesh.TriangleIndices.Add(5);

            //left face
            mesh.TriangleIndices.Add(0);
            mesh.TriangleIndices.Add(3);
            mesh.TriangleIndices.Add(7);
            mesh.TriangleIndices.Add(7);
            mesh.TriangleIndices.Add(4);
            mesh.TriangleIndices.Add(0);

            //up face
            mesh.TriangleIndices.Add(2);
            mesh.TriangleIndices.Add(6);
            mesh.TriangleIndices.Add(7);
            mesh.TriangleIndices.Add(7);
            mesh.TriangleIndices.Add(3);
            mesh.TriangleIndices.Add(2);

            //bottom face
            mesh.TriangleIndices.Add(0);
            mesh.TriangleIndices.Add(4);
            mesh.TriangleIndices.Add(5);
            mesh.TriangleIndices.Add(5);
            mesh.TriangleIndices.Add(1);
            mesh.TriangleIndices.Add(0);

            mGeometry = new GeometryModel3D(mesh,
                new DiffuseMaterial(Brushes.YellowGreen));
            group.Children.Add(mGeometry);

            //mesh = new MeshGeometry3D();
            //mesh.Positions.Add(new Point3D(-0.5, 0.5, 1));
            //mesh.Positions.Add(new Point3D(0.5,0.5, 1));
            //mesh.Positions.Add(new Point3D(1, 1, -1));
            //mesh.Positions.Add(new Point3D(-1, 1, -1));

            //mesh.TriangleIndices.Add(0);
            //mesh.TriangleIndices.Add(1);
            //mesh.TriangleIndices.Add(2);
            //mesh.TriangleIndices.Add(2);
            //mesh.TriangleIndices.Add(3);
            //mesh.TriangleIndices.Add(0);

            //  mGeometry = new GeometryModel3D(mesh, new DiffuseMaterial(Brushes.OrangeRed));

            //group.Children.Add(mGeometry);

            mGeometry.Transform = new Transform3DGroup();
         }

        AutoUpdateMessageBL message;
        ObservableCollection<string> StringCollection = new ObservableCollection<string>();
        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            message = new AutoUpdateMessageBL();
            message.FistPageMessageReceived = FistMessageReceivedFun;
            message.NewMessageReceived = FistMessageReceivedFun;
            message.OnExceptionOccured = (ex) => {
                MessageBox.Show(ex.Message);
            };
            lstTest.ItemsSource = StringCollection;

        }

        private void FistMessageReceivedFun(List<string> message)
        {
            this.Dispatcher.BeginInvoke(new Action(() =>
                {
                    message.ForEach(m => StringCollection.Insert(0,m));
                }), System.Windows.Threading.DispatcherPriority.Background);
        }

        #region 3D

        private void Grid_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            camera.Position = new Point3D(
                camera.Position.X,
                camera.Position.Y,
                camera.Position.Z - e.Delta / 120);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            camera.Position = new Point3D(
                camera.Position.X,
                camera.Position.Y,
                5);
            camera.LookDirection = new Vector3D(0, 0, -10);
        }

        private bool mDown;
        private Point mLastPos;

        private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.LeftButton != MouseButtonState.Pressed)
            {
                return;
            }
            mDown = true;

            Point pos = Mouse.GetPosition(viewport);
            mLastPos = new Point(pos.X - viewport.ActualWidth / 2, viewport.ActualHeight / 2 - pos.Y);
        }

        private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
        {
            mDown = false;
        }

        private void Grid_MouseMove(object sender, MouseEventArgs e)
        {
            if (!mDown)
            {
                return;
            }

            Point pos = Mouse.GetPosition(viewport);
            Point actualPos = new Point(pos.X - viewport.ActualWidth / 2, viewport.ActualHeight / 2 - pos.Y);
            double dx = actualPos.X - mLastPos.X;
            double dy = actualPos.Y - mLastPos.Y;

            double mouseAngle = 0;
            if (dx != 0 && dy != 0)
            {
                mouseAngle = Math.Asin(Math.Abs(dy) / Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2)));

                if (dx < 0 && dy > 0)
                {
                    mouseAngle += Math.PI / 2;
                }
                else if (dx < 0 && dy < 0)
                {
                    mouseAngle += Math.PI;
                }
                else if (dx > 0 && dy < 0)
                {
                    mouseAngle += Math.PI * 1.5;
                }
            }
            else if (dx == 0 && dy != 0)
            {
                mouseAngle = Math.Sign(dy) > 0 ? Math.PI / 2 : Math.PI * 1.5;
            }
            else if (dx != 0 && dy == 0)
            {
                mouseAngle = Math.Sign(dx) > 0 ? 0 : Math.PI;
            }

            double axisAngle = mouseAngle + Math.PI / 2;
            Vector3D axis = new Vector3D(Math.Cos(axisAngle) * 4, Math.Sin(axisAngle) * 4, 0);

            double rotation = 0.02 * Math.Sqrt(Math.Pow(dx, 2) + Math.Pow(dy, 2));

            Transform3DGroup group = mGeometry.Transform as Transform3DGroup;
            QuaternionRotation3D r =
                 new QuaternionRotation3D(
                 new Quaternion(axis, rotation * 180 / Math.PI));
            group.Children.Add(new RotateTransform3D(r));

            mLastPos = actualPos;
        } 
        #endregion

        private void btnAddImage_Click(object sender, RoutedEventArgs e)
        {
            ImageCapture capture = new ImageCapture();
            if (capture.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                MemoryStream stream = new MemoryStream();
                capture.Image.Save(stream, ImageFormat.Png);

                BitmapImage bitmap = new BitmapImage();
                bitmap.BeginInit();
                bitmap.StreamSource = stream;
                bitmap.EndInit();

                Image image = new Image();
                image.Source = bitmap;
                image.Stretch = Stretch.None;
                myRTB.InsertImage(image);
            }
        }

        private void btnShowContent_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(myRTB.Text);
            //ImageCapture capture = new ImageCapture();
            //if (capture.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            //{
            //    MemoryStream stream = new MemoryStream();
            //    capture.Image.Save(stream, ImageFormat.Png);

            //    BitmapImage bitmap = new BitmapImage();
            //    bitmap.BeginInit();
            //    bitmap.StreamSource = stream;
            //    bitmap.EndInit();

            //    Image a = new Image();
            //    a.Source = bitmap;
            //    a.Stretch = Stretch.None;

            //    //if (document.Blocks.Count == 0)
            //    //{
            //    //    Paragraph para = new Paragraph();
            //    //    document.Blocks.Add(para);
            //    //}

            //    //(document.Blocks.FirstBlock as Paragraph).Inlines.Add(a);
            //    //Figure figure = new Figure();
            //    //figure.Width = new FigureLength(200);
            //    //BlockUIContainer container = new BlockUIContainer(a);
            //    //figure.Blocks.Add(container);
            //    //Paragraph para = new Paragraph();
            //    //para.TextAlignment = TextAlignment.Left;
            //    //if (para.Inlines.FirstInline == null)
            //    //{
            //    //    para.Inlines.Add(figure);
            //    //}
            //    //else
            //    //{
            //    //    para.Inlines.InsertAfter(para.Inlines.FirstInline, figure);

            //    //}
            //    //fld.Blocks.Add(para);
            //}
 
            ////TextPointer position = rtb.Document.ContentStart;
            ////Image image=null;

            ////TextRange tx = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);

            ////while (position != null)
            ////{
            ////    if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.EmbeddedElement)
            ////    {
            ////       DependencyObject dp =  position.GetAdjacentElement(LogicalDirection.Forward);
            ////       if (dp.GetType() == typeof(Image))
            ////       {
            ////           if (image != null)
            ////           {
            ////               if (MessageBox.Show("你粘贴了多张图片，只有第一张图片会被发表" + Environment.NewLine + "返回编辑么？", "询问", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
            ////               {
            ////                   return;
            ////               };
            ////               break;
            ////           }
            ////           else
            ////           {
            ////               image = dp as Image;
            ////           }
            ////       }
            ////    }
            ////    position = position.GetNextContextPosition(LogicalDirection.Forward);
            ////}

            ////RenderTargetBitmap render = new RenderTargetBitmap((int)image.ActualWidth, (int)image.ActualHeight, 0, 0, PixelFormats.Default);
            ////render.Render(image);
            ////BmpBitmapEncoder encoder = new BmpBitmapEncoder();
            ////encoder.Frames.Add(BitmapFrame.Create(render));
            ////encoder.Frames.Add(BitmapFrame.Create(render));
            ////System.IO.Stream io = new FileStream(@"c:\a.jpg", FileMode.OpenOrCreate);
            ////encoder.Save(io);
            
            ////io.Close();
            //rtb.CaretPosition = rtb.Document.ContentEnd;
            //rtb.ScrollToEnd();
            //rtb.Focus();
        }

        private void rtb_TextChanged(object sender, TextChangedEventArgs e)
        {
            RichTextBox rt = new RichTextBox();
        }

        private void btnInsertText_Click(object sender, RoutedEventArgs e)
        {
            myRTB.InsertText("Hello");
        }

        private void btnGetImagesCount_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("images count:" + myRTB.GetImages().Count.ToString());
        }

        private void btnClear_Click(object sender, RoutedEventArgs e)
        {
            myRTB.ClearContent();
        }
 

        private void btnSpeak_Click(object sender, RoutedEventArgs e)
        {
            System.Speech.Synthesis.SpeechSynthesizer s = new SpeechSynthesizer();
            s.SpeakAsync(myRTB.Text);
        }

        private void btnSaveImages_Click(object sender, RoutedEventArgs e)
        {
            List<Image> images = myRTB.GetImages();
            int i = 0;
            foreach (var image in images)
            {
                image.Stretch = Stretch.None;
                RenderTargetBitmap render = new RenderTargetBitmap((int)image.Source.Width, (int)image.Source.Height, 0, 0, PixelFormats.Default);
                render.Render(image);
                BmpBitmapEncoder encoder = new BmpBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(render));
                System.IO.Stream io = new FileStream(@"c:\" + i +".jpg", FileMode.OpenOrCreate);
                encoder.Save(io);
                i++;
            }
        }

        private void btnStartTimer_Click(object sender, RoutedEventArgs e)
        {
            message.StartFetchingMessage();
        }

        private void btnChangeTimerInterval_Click(object sender, RoutedEventArgs e)
        {
            message.ResetUpdateInterval(1000);
        }
    }

    class AutoUpdateMessageBL
    {
        public Action<List<String>> NewMessageReceived;
        public Action<List<String>> FistPageMessageReceived;
        public Action<Exception> OnExceptionOccured;
        System.Timers.Timer timer = new System.Timers.Timer(3000);
        
        public void StartFetchingMessage()
        {
            //ThreadPool.QueueUserWorkItem(new WaitCallback((o)=>{
                try
                {
                    if (FistPageMessageReceived != null)
                    {
                        List<string> temp = new List<string>();
                        temp.Add("0");
                        temp.Add("1");
                        temp.Add("2");
                        FistPageMessageReceived(temp);
                    }

                    timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
                    timer.Start();
                }
                catch (Exception)
                {
                    throw;
                }
                
            //})); 
        }
        public void ResetUpdateInterval(double interval)
        {
            timer.Stop();
            timer.Interval = interval;
            timer.Start();
        }
        int i = 0;
        void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            //System.Threading.Thread.Sleep(4000);
            IncreateNumber();
        }

        void IncreateNumber()
        {
            try
            {
                i++;
                if (i >= 3)
                {
                    throw new Exception("max count exceeded!");
                }
                if (NewMessageReceived != null)
                {
                    List<string> temp = new List<string>();
                    temp.Add(DateTime.Now.Millisecond.ToString());
                    NewMessageReceived(temp);
                }
            }
            catch (Exception ex)
            {
                if (OnExceptionOccured != null)
                {
                    OnExceptionOccured(ex);
                }
            }
           
        }
    }
}
